function varargout = RFNN(varargin)
% RFNN MATLAB code for RFNN.fig
%      RFNN, by itself, creates a new RFNN or raises the existing
%      singleton*.
%
%      H = RFNN returns the handle to a new RFNN or the handle to
%      the existing singleton*.
%
%      RFNN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in RFNN.M with the given input arguments.
%
%      RFNN('Property','Value',...) creates a new RFNN or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before RFNN_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to RFNN_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help RFNN

% Last Modified by GUIDE v2.5 24-Nov-2012 19:35:02

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @RFNN_OpeningFcn, ...
                   'gui_OutputFcn',  @RFNN_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
end

% --- Executes just before RFNN is made visible.
function RFNN_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to RFNN (see VARARGIN)

% Choose default command line output for RFNN
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes RFNN wait for user response (see UIRESUME)
% uiwait(handles.RFNN);
end

% --- Outputs from this function are returned to the command line.
function varargout = RFNN_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;
end


% --- Executes on button press in btnConfig.
function btnConfig_Callback(hObject, eventdata, handles)
% hObject    handle to btnConfig (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    h = figure(Config);
    X = handles.X;
  %  figHandles = findall(0,'Type','figure');
  %  figHandles = findall('Type','figure','Tag','Config');
  a = findall(gcf); 
  c = findall(a,'Tag','txtInput');
  set(c,'String',size(X,2));
    waitfor(h);
   
    info_array = get(handles.RFNN, 'UserData');
    if(not(isempty(info_array)))
        handles.info = info_array;
        guidata(hObject,handles);
        msgbox('Variable saved','Saved');
        disp('OK');
        set(handles.btnRun,'Enable','on');
        set(handles.btnTest,'Enable','on');
         set(handles.btnCompare,'Enable','on');
    end
end

% --- Executes on button press in btnRun.
function btnRun_Callback(hObject, eventdata, handles)
% hObject    handle to btnRun (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
   
    
    
    % Convert output y
    yy = handles.y;
    XX =handles.X;
    %tempY = zeros(size(handles.y,1),10);
    %for i =1:size(handles.y,1)
   %     t = zeros(1,10);
    %    t(yy(i)+1) = 1;
    %    tempY(i,:) = t;
    %end
    %handles.y = tempY;
    guidata(hObject,handles);
    %get config information.
    tempVector = handles.info;
    vectorInit = tempVector;
    
    
    %Get info about RFNN. input, output, rules
    M_rules = int32(vectorInit(3)); % number of rules
    %N = int32(vectorInit(1));  %number of input.
    
    N = size(XX,2);
    vectorInit(1) = N;
    P = int32(vectorInit(2));
    %first layer have N  nodes N = 400
    % second layer have N x M nodes
    % third layer have M nodes
    % final layer have 10 nodes.
    
    %Random initialization
    randBegin = 5; randEnd = 10;
    interval = randEnd - randBegin;
    
    w = rand(M_rules,P).*interval + randBegin;    % Trong so w between layer 3 and layer 4
    wError = zeros(M_rules,P);
    
    
    m = rand(N,M_rules).*interval + randBegin;           % Trong tam  of Gauss
    mError = zeros(N,M_rules);
    
    xichma = rand(N,M_rules).*interval + randBegin;      % Do rong xichma of Gauss because divide we must init it value 1.
    xichmaError = zeros(N,M_rules);
    
    theta = rand(N,M_rules).*interval+ randBegin;       % Thong so hoi tiep. trong layer 2
    thetaError = zeros(N,M_rules);
    
    % Algorigthm.
    % Find value yk.
    % Find Error.
    % Update parameter.
    output2 = zeros(N,M_rules);
    tempOutput2 = output2;
    
    
    output3 = zeros(1,M_rules); % 1 vector M phan tu.
    output4 = zeros(1,P);
    
    %Save initia value of RFNN
    save('w_init.mat', 'w');
    save('m_init.mat','m'); save('xichma_init.mat','xichma'); save('theta_init.mat','theta'); save('ouput2_init.mat','output2');
    save('config_factor.mat','vectorInit');
    
    
    %Get minimum, maximum input value for each column.
    minInputEachColumArray = zeros(size(XX,2));
    maxInputEachColumArray = zeros(size(XX,2));
    for ii = 1: size(XX,2)
        minInputEachColumArray(ii) = min(XX(:,ii));
        maxInputEachColumArray(ii) = max(XX(:,ii));
    end
    %Get minimum, maxum output value for colum ouput.
    minOutput = min(yy); maxOutput = max(yy);
    
    %Save these value
    handles.minOutput = minOutput;
    handles.maxOutput = maxOutput;
    
    
    iCount = 0;
    
    %Trainning tren 90 percent bo du lieu.
    % 10percent de test
    iNum = size(handles.X,1);
    iRepeat = iNum*0.9;
for i=1:1:iRepeat      % Lap tren 4500 bo
      
      iCount = iCount + 1;
      
      % Canculate value of output1. Must be scale it.
      output1 = XX(i,:);
      for ii =1:size(output1,2)
          output1(ii) = (output1(ii) - minInputEachColumArray(ii))/(maxInputEachColumArray(ii) - minInputEachColumArray(ii));
      end

      
      % Canculate value at output2. Must be scale it. Must be check xichma
      % is zero or not and check if output2 is zero must be scale it.
      for ii = 1:N
          for jj = 1:M_rules
             if(xichma(ii,jj) == 0)
                 xichma(ii,jj) = 0.01;
             end
             output2(ii,jj) = exp(-(output1(ii) + theta(ii,jj)*tempOutput2(ii,jj) - m(ii,jj))^2/xichma(ii,jj)^2);
             if(output2(ii,jj) == 0)
                 output2(ii,jj) = 0.01;
             end
          end
      end
      
    
      %Canculate value at output3. It exactly.
      for jj = 1:M_rules
          S = 1;
          for ii =1:N
              S = S * output2(ii,jj);
          end
          output3(1,jj) = S;  
      end
      
      %Canculate value at ouput4.
      for k = 1:P
          output4(1,k) = 0;
          for ii = 1:M_rules
               output4(1,k) =  output4(1,k) + output3(1,ii) * w(ii,k);
          end
      end
      
      
      % Calculate error.
      % change output y. Remember.
      %tt = output4 - tempY(i,:);
      %[maxE ind] = max(output4);
      % temp_output4 = output4 ./ maxE;
      
      %for mm = 1: P
      %    if(temp_output4(mm) >= 0.99) 
     %         temp_output4(mm) = 1;
      %    else
      %        temp_output4(mm) = 0;
      %    end
      %end
      %[C index] = max(tempY(i,:));
      %E = 0.5 *( ind - index )^2;
      %E = 0.5 * dot((temp_output4 - tempY(i,:)),(temp_output4 - tempY(i,:)));
      %E = 0.5 * (output4 - yy(i))^2;
      
      temp = 0;
      currentErrorValueOfEachOuput = zeros(1,P);
      for ii = 1:P
          fuzzyVal = (yy(i,ii) - minOutput)/(maxOutput - minOutput);
          temp = temp + (fuzzyVal - output4(1,ii))^2;
          currentErrorValueOfEachOuput(1,ii) = fuzzyVal - output4(1,ii);
      end;
      E = temp/2;
      
      %plot 
      %set(handles.editError,'String','Hello');
      %plot(handles.graph,iCount,E);
      
       figure(2);
       ylabel('Error');
       xlabel('No.');
      
      % plot(iCount,E,'r+','LineWidth',2,...
      %                'MarkerEdgeColor','k',...
      %                 'MarkerFaceColor','g',...
      %                 'MarkerSize',5);
      plot(iCount,E,'r+');
      hold all;
      
      
      
      %Get learning rate and momentum.
      learning_rate_w = vectorInit(7);
      learning_rate_m = vectorInit(4);
      learning_rate_theta = vectorInit(6);
      learning_rate_xichma = vectorInit(5);
      momentum = vectorInit(8);
      

      %Canculate error wError.
      for ii=1:M_rules
         for jj = 1: P
             wError(ii,jj) = currentErrorValueOfEachOuput(1,jj) * output3(1,jj) * learning_rate_w + momentum*  wError(ii,jj);
         end
      end
      
      %Canculate error mError, xichmaError, phiError
      for jj = 1:M_rules
          temp = 0;
          for kk = 1: P
              temp = temp + currentErrorValueOfEachOuput(1,kk) * w(jj,kk);
          end
          for ii = 1: N
              tempErr = output1(ii) + tempOutput2(ii,jj)* theta(ii,jj) - m(ii,jj);
              mError(ii,jj) = temp* output3(jj) * 2 * tempErr / xichma(ii,jj)^2 * learning_rate_m + momentum * mError(ii,jj);
              xichmaError(ii,jj) = temp*output3(jj)*2* tempErr * tempErr / xichma(ii,jj) ^ 3 * learning_rate_xichma + momentum* xichmaError(ii,jj);
              thetaError(ii,jj) = temp*output3(jj)*(-2)*tempErr*tempOutput2(ii,jj)/xichma(ii,jj)^2 * learning_rate_theta + momentum*thetaError(ii,jj);
          end
      end
      
      %Update error and tempOuput2
      tempOutput2 = output2;
      m = m + mError;
      xichma = xichma + xichmaError;
      theta = theta + thetaError;
      w = w + wError;
end
   
   
    %Save result.
    handles.w = w;
    handles.m = m;
    handles.xichma = xichma;
    handles.theta = theta;
    handles.output2 = output2;
    save('w_final.mat', 'w');
    save('m_final.mat','m'); save('xichma_final.mat','xichma'); save('theta_final.mat','theta'); save('ouput2_final.mat','output2');
    save('ouput4_final.mat', 'output4');
    guidata(hObject,handles);

end

% --------------------------------------------------------------------
function menuFile_Callback(hObject, eventdata, handles)
% hObject    handle to menuFile (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
end


% --------------------------------------------------------------------
function menuLoad_Callback(hObject, eventdata, handles)
% hObject    handle to menuLoad (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    [FileName,FilePath]=uigetfile();
    ExPath = [FilePath FileName];
    x = load(ExPath); % get X,Y. X is matrix 5000x400
    handles.X = x.X;
    handles.y = x.y;
    guidata(hObject,handles);
   % tableData
   %f = figure('Name','fuck','Position', [100 100 752 350]);
   % h = get(handles.tableData);
   %set(h,'Columns',10);
   %t = uitable('Tag','TableData','Parent', RFNN, 'Position', [10 10 752 350]);
   set(handles.datatable,'Data',x.X);
   %get 1 row. to show image.
   % reshape matrix.
  % m = reshape(x.X(501,:),20,20);
  % figure(2);
  % imshow(m);
   set(handles.btnConfig,'Enable','on');
   %TODO
   
end

% --------------------------------------------------------------------
function Exit_Callback(hObject, eventdata, handles)
    close(RFNN);
end

function btnConfig_ButtonDownFcn(hObject, eventdata, handles)

end



% --- Executes on button press in btnTest.
function btnTest_Callback(hObject, eventdata, handles)

    % Load file test => print list output4 on the graph.
    
    %Load m
    m1 = load('m_final.mat');
    m = m1.m;
    
    %Load theta
    theta1 = load('theta_final.mat');
    theta = theta1.theta;
    
    %Load w
    w1 = load('w_final.mat');
    w = w1.w;
    
    %Load xichma
    xichma1 = load('xichma_final.mat');
    xichma = xichma1.xichma;
    
   % m = handles.m;
   % w = handles.w;
   % theta = handles.theta;
   % xichma = handles.xichma;
    
    
    %Load learning rate and mometum
    vectorInit1  = load('config_factor.mat');
    vectorInit = vectorInit1.vectorInit;
    
    %Load parameter of RFNN M_rules, N: input,   P: output
    M_rules = int32(vectorInit(3)); % number of rules
    N = int32(vectorInit(1));  %number of input.
    P = int32(vectorInit(2));
    
    %Load pre output2
    temp_output2 = load('ouput2_final.mat');
    tempOutput2 = temp_output2.output2;
    output2 = zeros(N,M_rules);
    %tempOutput2 = handles.output2;
    output3 = zeros(1,M_rules); % 1 vector M phan tu.
    output4 = zeros(1,P);
    
    %Load max,min input, output.
    
    
    %Load test file.
    [FileName,FilePath]=uigetfile();
    ExPath = [FilePath FileName];
    a = load(ExPath);
    
    %Matrix input
    XX = a.X; 
    %yy = a.y;
    minInputEachColumArray = zeros(size(XX,2));
    maxInputEachColumArray = zeros(size(XX,2));
    for ii = 1: size(XX,2)
        minInputEachColumArray(ii) = min(XX(:,ii));
        maxInputEachColumArray(ii) = max(XX(:,ii));
    end
   % minOutput = min(yy); maxOutput = max(yy);
    
    %Save these value
    minOutput =  handles.minOutput;
    maxOutput = handles.maxOutput;
    
    iCount = 0;
    for i = 1:size(XX,1)
       % output1 = reshape(I,400,1);
       iCount = iCount + 1;
      
      % Canculate value of output1. Must be scale it.
      output1 = XX(i,:);
      for ii =1:size(output1,2)
          output1(ii) = (output1(ii) - minInputEachColumArray(ii))/(maxInputEachColumArray(ii) - minInputEachColumArray(ii));
      end

      
      % Canculate value at output2. Must be scale it. Must be check xichma
      % is zero or not and check if output2 is zero must be scale it.
      for ii = 1:N
          for jj = 1:M_rules
             if(xichma(ii,jj) == 0)
                 xichma(ii,jj) = 0.01;
             end
             output2(ii,jj) = exp(-(output1(ii) + theta(ii,jj)*tempOutput2(ii,jj) - m(ii,jj))^2/xichma(ii,jj)^2);
             if(output2(ii,jj) == 0)
                 output2(ii,jj) = 0.01;
             end
          end
      end
      
    
      %Canculate value at output3. It exactly.
      for jj = 1:M_rules
          S = 1;
          for ii =1:N
              S = S * output2(ii,jj);
          end
          output3(1,jj) = S;  
      end
      
      %Canculate value at ouput4.
      for k = 1:P
          output4(1,k) = 0;
          for ii = 1:M_rules
               output4(1,k) =  output4(1,k) + output3(1,ii) * w(ii,k);
          end
          output4(1,k) = output4(1,k)*(maxOutput - minOutput) + minOutput;
      end
      
      tempOutput2 = output2;
      figure(2);
      ylabel('Price');
      xlabel('No.');
      %Do chi co 1 ouput.
      plot(iCount,output4(1,P),'r+');
      %plot(iCount,yy(i,1),'g+');
      hold all;
    end

    
end


% --- Executes on button press in btnCompare.
function btnCompare_Callback(hObject, eventdata, handles)
     

     
    % Convert output y
    yy = handles.y;
    XX =handles.X;
    
    guidata(hObject,handles);
    %get config information.
    tempVector = handles.info;
    vectorInit = tempVector;
    
    
    %Get info about RFNN. input, output, rules
    M_rules = int32(vectorInit(3)); % number of rules
    %N = int32(vectorInit(1));  %number of input.
    
    N = size(XX,2);
    vectorInit(1) = N;
    P = int32(vectorInit(2));

    %Random initialization
    randBegin = 5; randEnd = 10;
    interval = randEnd - randBegin;
    
    w = rand(M_rules,P).*interval + randBegin;    % Trong so w between layer 3 and layer 4
    wError = zeros(M_rules,P);
    
    
    m = rand(N,M_rules).*interval + randBegin;           % Trong tam  of Gauss
    mError = zeros(N,M_rules);
    
    xichma = rand(N,M_rules).*interval + randBegin;      % Do rong xichma of Gauss because divide we must init it value 1.
    xichmaError = zeros(N,M_rules);
    
    theta = rand(N,M_rules).*interval+ randBegin;       % Thong so hoi tiep. trong layer 2
    thetaError = zeros(N,M_rules);
    

    output2 = zeros(N,M_rules);
    tempOutput2 = output2;
    
    
    output3 = zeros(1,M_rules); % 1 vector M phan tu.
    output4 = zeros(1,P);
    
    %Save initia value of RFNN
  %  save('w_init.mat', 'w');
  %  save('m_init.mat','m'); save('xichma_init.mat','xichma'); save('theta_init.mat','theta'); save('ouput2_init.mat','output2');
  %  save('config_factor.mat','vectorInit');
    
    
    %Load m
    m1 = load('m_final.mat');
    m = m1.m;
    
    %Load theta
    theta1 = load('theta_final.mat');
    theta = theta1.theta;
    
    %Load w
    w1 = load('w_final.mat');
    w = w1.w;
    
    %Load xichma
    xichma1 = load('xichma_final.mat');
    xichma = xichma1.xichma;
    
    %Load pre output2
    temp_output2 = load('ouput2_final.mat');
    tempOutput2 = temp_output2.output2;
    output2 = zeros(N,M_rules);
    %tempOutput2 = handles.output2;
    output3 = zeros(1,M_rules); % 1 vector M phan tu.
    output4 = zeros(1,P);
    
    %Get minimum, maximum input value for each column.
    minInputEachColumArray = zeros(size(XX,2));
    maxInputEachColumArray = zeros(size(XX,2));
    for ii = 1: size(XX,2)
        minInputEachColumArray(ii) = min(XX(:,ii));
        maxInputEachColumArray(ii) = max(XX(:,ii));
    end
    %Get minimum, maxum output value for colum ouput.
    minOutput = min(yy); maxOutput = max(yy);
    
    %Save these value
    handles.minOutput = minOutput;
    handles.maxOutput = maxOutput;
    
    
    iCount = 0;
    
    %Trainning tren 90 percent bo du lieu.
    % 10percent de test
    iNum = size(handles.X,1);
    iRepeat = iNum*0.9;
for i=round(iRepeat):1:iNum      % Lap tren 4500 bo
      
      iCount = iCount + 1;
      
      % Canculate value of output1. Must be scale it.
      output1 = XX(i,:);
      for ii =1:size(output1,2)
          output1(ii) = (output1(ii) - minInputEachColumArray(ii))/(maxInputEachColumArray(ii) - minInputEachColumArray(ii));
      end

      
      % Canculate value at output2. Must be scale it. Must be check xichma
      % is zero or not and check if output2 is zero must be scale it.
      for ii = 1:N
          for jj = 1:M_rules
             if(xichma(ii,jj) == 0)
                 xichma(ii,jj) = 0.01;
             end
             output2(ii,jj) = exp(-(output1(ii) + theta(ii,jj)*tempOutput2(ii,jj) - m(ii,jj))^2/xichma(ii,jj)^2);
             if(output2(ii,jj) == 0)
                 output2(ii,jj) = 0.01;
             end
          end
      end
      
    
      %Canculate value at output3. It exactly.
      for jj = 1:M_rules
          S = 1;
          for ii =1:N
              S = S * output2(ii,jj);
          end
          output3(1,jj) = S;  
      end
      
      %Canculate value at ouput4.
      for k = 1:P
          output4(1,k) = 0;
          for ii = 1:M_rules
               output4(1,k) =  output4(1,k) + output3(1,ii) * w(ii,k);
          end
      end
      
       
      
      
      temp = 0;
      currentErrorValueOfEachOuput = zeros(1,P);
      for ii = 1:P
          fuzzyVal = (yy(i,ii) - minOutput)/(maxOutput - minOutput);
          temp = temp + (fuzzyVal - output4(1,ii))^2;
          currentErrorValueOfEachOuput(1,ii) = fuzzyVal - output4(1,ii);
           
          figure(2);
           ylabel('Price');
           xlabel('No.');

          plot(iCount,yy(i,ii),'r+');
          plot(iCount,output4(1,ii)*(maxOutput - minOutput) + minOutput ,'g+');
          hold all;
      end;
      
      %{
      %Get learning rate and momentum.
      learning_rate_w = vectorInit(7);
      learning_rate_m = vectorInit(4);
      learning_rate_theta = vectorInit(6);
      learning_rate_xichma = vectorInit(5);
      momentum = vectorInit(8);
      

      %Canculate error wError.
      for ii=1:M_rules
         for jj = 1: P
             wError(ii,jj) = currentErrorValueOfEachOuput(1,jj) * output3(1,jj) * learning_rate_w + momentum*  wError(ii,jj);
         end
      end
      
      %Canculate error mError, xichmaError, phiError
      for jj = 1:M_rules
          temp = 0;
          for kk = 1: P
              temp = temp + currentErrorValueOfEachOuput(1,kk) * w(jj,kk);
          end
          for ii = 1: N
              tempErr = output1(ii) + tempOutput2(ii,jj)* theta(ii,jj) - m(ii,jj);
              mError(ii,jj) = temp* output3(jj) * 2 * tempErr / xichma(ii,jj)^2 * learning_rate_m + momentum * mError(ii,jj);
              xichmaError(ii,jj) = temp*output3(jj)*2* tempErr * tempErr / xichma(ii,jj) ^ 3 * learning_rate_xichma + momentum* xichmaError(ii,jj);
              thetaError(ii,jj) = temp*output3(jj)*(-2)*tempErr*tempOutput2(ii,jj)/xichma(ii,jj)^2 * learning_rate_theta + momentum*thetaError(ii,jj);
          end
      end
      
      %Update error and tempOuput2
      tempOutput2 = output2;
      m = m + mError;
      xichma = xichma + xichmaError;
      theta = theta + thetaError;
      w = w + wError;
      %}
end
    handles.w = w;
    handles.m = m;
    handles.xichma = xichma;
    handles.theta = theta;
    handles.output2 = output2;
   % save('w_final.mat', 'w');
   % save('m_final.mat','m'); save('xichma_final.mat','xichma'); save('theta_final.mat','theta'); save('ouput2_final.mat','output2');
   % save('ouput4_final.mat', 'output4');
    guidata(hObject,handles);

end
